/*
 *  $Id: Defence.cs 1233 2010-12-18 17:54:48Z thenn.erannor $
 *  This file is a part of Ragima CCG.
 *  (C) 2008-2010 Ragima development group.
 *
 *  Licensed under the terms of the GNU GPL License version 2.
 *
 */

using System.Collections.Generic;

using Nereal.Serialization;

namespace Ragima {
    /// <summary>
    /// Тип цели: место для перемещения и блокируемые вражеские существа.
    /// </summary>
    public class DefenceTarget : MoveTarget {
        public DefenceTarget(Creature creature) : base(creature) {
        }

        public override int GetCount(AbstractObject caster) {
            int count = base.GetCount(caster);
            if (_creature.State == CreatureState.Untapped || _creature.State == CreatureState.Defence) {
                bool allBlocks = _creature.Owner.GetDefencesCount(_creature) >= _creature.Summary.GetBlocks();
                foreach (var attacker in _creature.Owner.Enemy.GetBlockedAttackers(_creature))
                    if (!allBlocks || attacker.Defenders.Contains(_creature))
                        count++;
            }
            return count;
        }

        public override bool AcceptRegion(Region region) {
            if (_creature.State != CreatureState.Untapped && _creature.State != CreatureState.Defence)
                return false;
            var pcr = region as PlayerCreatureRegion;
            if (pcr == null || !pcr.IsEnemy)
                return false;
            if (pcr.Creature.State != CreatureState.Offence)
                return false;
            bool allBlocks = Request.Player.GetDefencesCount(_creature) >= _creature.Summary.GetBlocks();
            if (_creature.CanBlock(pcr.Creature) && (!allBlocks || pcr.Creature.Defenders.Contains(_creature)))
                return true;
            return false;
        }

        public override TargetArgs GetArgs(Region region) {
            var pcr = region as PlayerCreatureRegion;
            return pcr != null ? new DefendTargetArgs(Request.Player, Request.Caster, pcr.Creature) : base.GetArgs(region);
        }
    }

    [TypeId("defend")]
    public class DefendTargetArgs : CreatureActionTargetArgs {
        [XmlName("attacker"), Reference(true, typeof(string), Serialization.Resolvers.GameCreature)]
        public Creature Attacker;

        public DefendTargetArgs() {
        }
        public DefendTargetArgs(Player player, AbstractObject caster, Creature attacker) : base(player, caster) {
            Attacker = attacker;
        }

        protected override void DoAction(Creature cr) {
            if (Attacker.Defenders.Contains(cr))
                UnsetDefence(cr);
            else
                SetDefence(cr);
        }

        private void SetDefence(Creature defender) {
            if (defender.HasFlag<Affects.MassBlock>()) {
                var attackers = new List<Creature>(Attacker.Owner.GetBlockedAttackers(defender));
                defender.Owner.SetDefence(defender, attackers, true);
            } else
                defender.Owner.SetDefence(defender, Attacker, true);
        }
        private void UnsetDefence(Creature defender) {
            if (defender.HasFlag<Affects.SlowAfterAttack>())
                return;
            if (defender.HasFlag<Affects.MassBlock>())
                defender.Owner.UnsetDefence(defender);
            else
                defender.Owner.UnsetDefence(defender, Attacker);
        }
    }
}
